Skip to content

简介

网页端运行的ffmpeg,纯靠网页中的依赖,不需要依赖环节变量ffmpeg。 具体与命令行工具具体有何区别,没空研究,性能估计只有本体的三分之一。

前言

记录当前文档的主要原因,是此依赖包有过一次大版本更新,大量的最新api没有被llm大语言模型收录,查阅资料的时候极其容易跑偏。 故此,当前文档内每一个功能都完成了可行性验证。

信息

version:"@ffmpeg/ffmpeg": "^0.12.15", "@ffmpeg/util": "^0.12.2" data:2025/08/18

创建

依赖

npm install @ffmpeg/ffmpeg @ffmpeg/util

vite.config.ts

ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  server: {
    headers: {
      'Cross-Origin-Embedder-Policy': 'require-corp',
      'Cross-Origin-Opener-Policy': 'same-origin',
    },
  },
  worker: {
    format: 'es',
  },
  plugins: [vue()],
  optimizeDeps: {
    exclude: ["@ffmpeg/ffmpeg"]  // *重点 - 防止预构建的过程中丢失路径
  }
})

加载

ts
import { FFmpeg } from '@ffmpeg/ffmpeg'
import { fetchFile, toBlobURL } from '@ffmpeg/util'

const ffmpeg = new FFmpeg();  // 新的版本需要在此导入实例
onMounted(async () => {
  const baseURL = '/ffmpeg'  // 考虑网络稳定性,建议下载到public
  // const baseURL = 'https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm'
  await ffmpeg.load({
    coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
    wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
    workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
  });
  console.log('ffmpeg加载完成');
})

常用方法

独立功能实现

截取时间

本part主要关注,基于原本封装格式不变,裁切视频内容。

ts
const transcode = async (
	{ type, file, input, output }: 
	{ type: string, file: File, input: number, output: number }
) => {
  const buffer = new Uint8Array(await fetchFile(URL.createObjectURL(file)));
  await ffmpeg.writeFile('input.' + type, buffer);
  await ffmpeg.exec([
    '-i', `input.${type}`,      // 输入
    '-ss', input + '',          // 开始时间
    '-t', output - input + '',  // 持续时间
    '-c', 'copy',               // 直接复制流,*速度极快*
    `output.${type}`
  ]);
  const data = await ffmpeg.readFile('output.' + type);
  download(data);
}

编解码

本part主要关注,将不同格式的文件转换成mp4文件。

分辨率

本part主要关注,基于一个固定分辨率的画布上,加入视频素材。

变形

本part主要关注,位移、缩放、旋转

组合拳

组合实现

叠轨

相关方法

download
js
const download = (data,type) => {
  const a = document.createElement('a');
  a.href = URL.createObjectURL(new Blob([data.buffer], { type: 'type/type' }))
  a.download = 'output.type';
  a.click();
  a.remove();
}